#include"chen.h"

int
main( int argc, char **argv )
{
	int tcpfd, udpfd, connfd, nready, maxfd1;
	socklen_t len;
	fd_set rset;
	pid_t childpid;
	const int on = 1;
	
	void sig_chld( int );

	struct sockaddr_in servaddr, cliaddr;

	char buff[MAXLINE];
	ssize_t n;

	tcpfd = Socket( AF_INET, SOCK_STREAM, 0 );
	bzero( &servaddr, sizeof( servaddr ) );
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
	servaddr.sin_port = htons( SERV_PORT );

	setsockopt( tcpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof( on ) );

	Bind( tcpfd, ( struct sockaddr * )&servaddr, sizeof( servaddr ) );
	Listen( tcpfd, LISTENQ );

	udpfd = Socket( AF_INET, SOCK_DGRAM, 0 );
	bzero( &servaddr, sizeof( servaddr ) );
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
	servaddr.sin_port = htons( SERV_PORT );

	Bind( udpfd, ( struct sockaddr * )&servaddr, sizeof( servaddr ) );
	
	signal( SIGCHLD, sig_chld );
	maxfd1 = max( tcpfd, udpfd ) + 1;
	
	for ( ; ; ) {
		FD_SET( tcpfd, &rset );
		FD_SET(	udpfd, &rset );
		if ( ( nready = select( maxfd1, &rset, NULL, NULL, NULL ) ) < 0 ) {
			if ( errno == EINTR )
				continue;
			else
				err_sys( "select error" );
		}

		if ( FD_ISSET( tcpfd, &rset ) ) {
			len = sizeof( cliaddr );
			connfd = Accept( tcpfd, ( struct sockaddr * )&cliaddr, &len );
			
			Fputs( "use tcp", stdout );
			if ( ( childpid = Fork( ) ) == 0 ) {
				close( tcpfd );
				str_echo( connfd );
				exit( 0 );
			}
			close( connfd );
		}

		if ( FD_ISSET( udpfd, &rset ) ) {
			len = sizeof( cliaddr );
			n = Recvfrom( udpfd, buff, MAXLINE, 0, ( struct sockaddr * )&cliaddr, &len );
			Sendto( udpfd, buff, n, 0, ( struct sockaddr * )&cliaddr, len );
		}
		
	}

}
